#!/usr/local/bin/python
################################################################################
#!/usr/local/develop/python/bin/python
# esmtpd.py
#
# UTF8SMTP NIDAMail Program
# Version 1.0
# Date : July 23, 2008
# Homepage: http://sourceforge.net/projects/utf8smtp/
################################################################################

from distutils import file_util
from email import base64MIME
from socket import *
import threading, time, os, re

################################################################################
# STARTTLS
from tlslite.api import *
################################################################################

import common

# Configuration
conf = common.conf
vh = common.vh
access = common.access

################################################################################
# Defining Functions for UTF8SMTP
# Load configuration from common.py
################################################################################

################################################################################
def validateEmail(email):
	if len(email) > 6:
		if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) != None:
			return 1
	return 0
################################################################################
def receiveESMTP(conn, addr):
	# Create a key (time value)
	key19 = common.makeKEY19(0)

	# Set timeout (Default = 600)
	conn.settimeout(conf['ESMTPD_TIMEOUT'])

	# sendall() - Send data to the socket. 
	try: conn.sendall('220 ESMTP %s\r\n' % common.PROGRAM_VERSION)
	except: common.printLOG("esmtpd | Cannot sendall(220 ESMTPD %s)" % common.PROGRAM_VERSION, 'error')

	# Print a log to a file /NIDAMail_Data/LOG/esmtpd_YYYYMMDD.log
	common.printLOG('%s | Connected from %s:%d(%d)' % (key19, addr[0], addr[1], threading.activeCount()), 'esmtpd')

	# Mail commands
	mail = {'AUTH_USER':'',
		'AUTH_PASS':'',
		'MAIL_FROM':'',
		'RCPT_TO':[],
		'RELAY_TO':[],
		'RELAY_TO_ALT':[],
		'ACCESS':'',
		'STATE':'HELO',
		'RECEIVED':1,
		'DOT':0,
		'MAIL_FROM_ALT':'',
		'RCPT_TO_ALT':[],
		}

	# addr[0]
	mail['ACCESS'] = common.search_access(addr[0], ['from', 'both'])[2]

	if mail['ACCESS'] == 'deny':
		try: conn.sendall('701 Access denied\r\n')
		except: common.printLOG("esmtpd | Cannot sendall('701 Access denied')", 'error')
		common.printLOG('%s | Access denied from %s:%d by IP rule' % (key19, addr[0], addr[1]), 'esmtpd')
		# Change a state to QUIT
		mail['STATE'] = 'QUIT'

	# Try to open /NIDAMail_Data/TEMP/"key19"
	try: 
		f = open('%s/%s' % (conf['RECV_QUEUE'], key19), 'w')
	except:
		common.printLOG("esmtpd  | Cannot open %s/%s" % (conf['RECV_QUEUE'], key19), 'error')
		# Change a state to QUIT
		mail['STATE'] = 'QUIT'
	############################################################################
	# mail['STATE'] is not equal to 'QUIT'
	############################################################################
	buffStr = ''
	while mail['STATE'] != 'QUIT':
		try:
			recvStr = conn.recv(1024) # recv(bufsize[, flags]) - Receive data from the socket.
			if recvStr == '':
				common.printLOG('%s | Disconnected from %s:%d by client' % (key19, addr[0], addr[1]), 'esmtpd')
				break
		except:
			common.printLOG('%s | Disconnected from %s:%d by client' % (key19, addr[0], addr[1]), 'esmtpd')
			break
		else:
			buffStr = buffStr + recvStr
			####################################################################
			# line process
			# string.find() - Return the lowest index in s where the substring sub is found such that sub is wholly contained in s[start:end]. Return -1 on failure.
			####################################################################
			# If there is no line feed (\n)
			if buffStr.find('\n') != -1:
				i = 0
				listStr = buffStr.splitlines()
				for lineStr in listStr:
					i = i + 1
					if not buffStr.endswith('\n') and i == len(listStr): break
					cmdStr = lineStr.upper()

					############################################################
					if mail['STATE'] != 'DOT': common.printLOG('%s | %s' % (key19, lineStr.strip()), 'esmtpd')
					############################################################
					#-----------------------------------------------------------
					# DATA command mode
					#-----------------------------------------------------------
					if mail['STATE'] == 'DOT':
						# If there is a DOT(.)
						if lineStr == '.':
							conn.sendall('250 Message accepted for delivery\r\n')
							# STATE -> NULL / DOT -> 1
							mail['STATE'] = ''
							mail['DOT'] = 1
						else:
							f.write('%s\r\n' % lineStr)
					#-----------------------------------------------------------
					# HELP
					#-----------------------------------------------------------
					elif cmdStr.startswith('HELP'):
						conn.sendall('214-This ESMTP server is a part of %s system. For\r\n'
										'214-information about the %s, please see %s\r\n'
										'214 Please report mail-related problems to %s\r\n' % (common.PROGRAM_NAME, common.PROGRAM_NAME, common.PROGRAM_HOMEPAGE, common.PROGRAM_MAIL))
					#-----------------------------------------------------------
					# HELO
					#-----------------------------------------------------------
					elif cmdStr.startswith('HELO'):
						conn.sendall('250 %s Hello %s, pleased to meet you\r\n' % (conf['SERVER_NAME'], addr[0]))
						mail['STATE'] = 'MAIL_FROM'
					#-----------------------------------------------------------
					# EHLO
					#-----------------------------------------------------------
					elif cmdStr.startswith('EHLO'):
						conn.sendall('250-%s Hello %s, pleased to meet you\r\n'
										'250-AUTH LOGIN\r\n'
										'250-8BITMIME\r\n'
										'250-UTF8SMTP\r\n'
										'250-STARTTLS\r\n'
										'250 HELP\r\n' % (conf['SERVER_NAME'], addr[0]))
						mail['STATE'] = 'MAIL_FROM'
					#-----------------------------------------------------------
					# EHLO
					#-----------------------------------------------------------
					elif cmdStr == 'STARTTLS':
						common.printLOG('%s | STARTTLS' % key19, 'esmtpd')
						try:
							x509Cert = X509().parse(open('/NIDAMail/conf/a.pem').read())
							x509Chain = X509CertChain([x509Cert])
							s = open('/NIDAMail/conf/a.pem').read()
							x509Key = parsePEMKey(s, private=True)
						except:
							conn.sendall('454 4.3.3 TLS not available due to temporary reason\r\n')
							common.printLOG("%s | Can't STARTTLS" % key19, 'esmtpd')
						else:
							conn.sendall('220 2.0.0 Ready to start TLS\r\n')
							connTLS = TLSConnection(conn)
							connTLS.handshakeServer(certChain=x509Chain, privateKey=x509Key)
							conn = connTLS
					#-----------------------------------------------------------
					# AUTH
					#-----------------------------------------------------------
					elif cmdStr.startswith('AUTH'):
						if cmdStr.startswith('AUTH LOGIN'):
							conn.sendall('334 VXNlcm5hbWU6\r\n')
							mail['STATE'] = 'AUTH_USER'
						else:
							conn.sendall('504 Unrecongnized authentication type\r\n')
					#-----------------------------------------------------------
					# In case of mail['STATE'] == 'AUTH_USER'
					#-----------------------------------------------------------
					elif mail['STATE'] == 'AUTH_USER':
						try: 
							mail['AUTH_USER'] = base64MIME.decode(lineStr.strip())
						except: 
							mail['AUTH_USER'] = ''

						mail['AUTH_USER'] = common.convertIDN(mail['AUTH_USER'])
						retStr = common.searchUserPath(mail['AUTH_USER'])[0]

						if retStr not in ('no user', 'no domain'):
							conn.sendall('334 UGFzc3dvcmQ6\r\n')
							mail['STATE'] = 'AUTH_PASS'
						else:
							conn.sendall('500 Authentication failed\r\n')
							common.printLOG('%s | 500 Authentication failed (%s)' % (key19, mail['AUTH_USER']), 'esmtpd')
							mail['STATE'] = 'QUIT'
							break
					#-----------------------------------------------------------
					# In case of mail['STATE'] == 'AUTH_PASS'
					#-----------------------------------------------------------
					elif mail['STATE'] == 'AUTH_PASS':
						try: mail['AUTH_PASS'] = base64MIME.decode(lineStr.strip())
						except: mail['AUTH_PASS'] = ''
						retInt = common.iscorrect_password(mail['AUTH_USER'], mail['AUTH_PASS'])
						if retInt == 1:
							conn.sendall('235 Authentication successful\r\n')
							common.printLOG('%s | 235 Authentication successful (%s)' % (key19, mail['AUTH_USER']), 'esmtpd')
							mail['STATE'] = 'MAIL_FROM'
							mail['ACCESS'] = 'relay'
						else:
							conn.sendall('500 Authentication failed\r\n')
							common.printLOG('%s | 500 Authentication failed (%s)' % (key19, mail['AUTH_USER']), 'esmtpd')
							mail['STATE'] = 'QUIT'
							break
					#-----------------------------------------------------------
					# cmdStr.startswith('MAIL FROM:') and mail['STATE'] == 'MAIL_FROM'
					#-----------------------------------------------------------
					elif cmdStr.startswith('MAIL FROM:') and mail['STATE'] == 'MAIL_FROM':
						#-------------------------------------------------------
						# EAI Implementation
						#-------------------------------------------------------
						# Check the length of MAIL FROM command
						# EAI SMTP Extension 2.1.4
						# The maximum length of MAIL and RCPT command : 460 characters
						lineStrLength = len(lineStr.decode('utf-8'))
						if (lineStrLength > 460):
							conn.sendall('550 5.5.4 %s... Syntax Error (460 characters limit)\r\n' % (lineStr))
							common.printLOG('%s | 550 %s... Syntax Error (460 characters limit)' % (key19, lineStr), 'esmtpd')

						# The number of occurrences of Left Angle Bracket
						lbracket = lineStr[10:].count('<')
						# The number of occurrences of Right Angle Bracket
						rbracket = lineStr[10:].count('>')

						# Need to add functions for the followings:
						# Email Regular Expression Syntax Validation Check for IDN@IDN
						if ((lbracket == 0) & (rbracket == 0)):
							print "Syntax Error - No angle brackets"
							conn.sendall('550 5.5.4 %s... Syntax Error\r\n' % (lineStr))
							common.printLOG('%s | 550 %s... Syntax Error' % (key19, lineStr), 'esmtpd')
						elif ((lbracket == 1) & (rbracket == 1)):
							#mail['MAIL_FROM'] = lineStr[10:].strip().strip('<>').lower()
							MAIL_FROM_STRIP = lineStr[10:].strip().strip('<').upper()

							# The lowest index in the string where "ALT-ADDRESS=" is found
							ALTADDRESS = MAIL_FROM_STRIP.decode('utf-8').find("ALT-ADDRESS=")
	
							#---------------------------------------------------		
							# If there is ALT-ADDRESS
							#---------------------------------------------------		
							if ( ALTADDRESS != -1 ):
								mail['MAIL_FROM'] = str(MAIL_FROM_STRIP.partition('>')[0].strip().lower())
								MAIL_FROM_ALT = str(MAIL_FROM_STRIP.decode('utf-8')[ALTADDRESS:].strip().lower())
								mail['MAIL_FROM_ALT'] = str(MAIL_FROM_ALT.decode('utf-8').partition('=')[2].strip().lower())
								# EAI SMTP Extension 2.4
								# ALT-ADDRESS value MUST be an all-ASCII email address
								if re.match("^[a-zA-Z0-9._%-]+@[a-zA-Z0-9._%-]+\.[a-zA-Z]{2,6}$", mail['MAIL_FROM_ALT']) == None:
									print "ALT-ADDRESS Syntax Error"
									conn.sendall('550 5.5.4 %s... Syntax Error\r\n' % (lineStr))
									common.printLOG('%s | 550 %s... Syntax Error' % (key19, lineStr), 'esmtpd')
							else:
								mail['MAIL_FROM'] = str(MAIL_FROM_STRIP.partition('>')[0].strip())
						else:
							print "Syntax Error"
							conn.sendall('550 5.5.4 %s... Syntax Error\r\n' % (lineStr))
							common.printLOG('%s | 550 %s... Syntax Error' % (key19, lineStr), 'esmtpd')
						print "MAIL FROM: " + mail['MAIL_FROM']
						print "MAIL FROM ALT: " + mail['MAIL_FROM_ALT']
						########################################################
						mail['MAIL_FROM'] = common.convertIDN(mail['MAIL_FROM'])
						#---------------------------------------------------------
						if common.search_access(mail['MAIL_FROM'], ['from', 'both'])[2] != '': 
							mail['ACCESS'] = common.search_access(mail['MAIL_FROM'], ['from', 'both'])[2]

						if mail['ACCESS'] == 'deny':
							try: conn.sendall('701 Access denied\r\n')
							except: common.printLOG("esmtpd  | Cannot sendall('701 Access denied')", 'error')
							common.printLOG('%s | Access denied from %s:%d by MAIL_FROM(%s) rule' % (key19, addr[0], addr[1], mail['MAIL_FROM']), 'esmtpd')
							mail['STATE'] = 'QUIT'
							break
						else:
							retStr = common.searchUserPath(mail['MAIL_FROM'])[0]
							if retStr == 'no user':
								try: conn.sendall('701 Access denied\r\n')
								except: common.printLOG("esmtpd | Cannot sendall('701 Access denied')", 'error')
								common.printLOG('%s | Access denied from %s:%d by MAIL_FROM(%s) no such user' % (key19, addr[0], addr[1], mail['MAIL_FROM']), 'esmtpd')
								mail['STATE'] = 'QUIT'
								break
							else:
								if mail['ACCESS'] in ('allow', 'relay'): 
									f.write('IS_ALLOW: yes\r\n')

								f.write('FROM_IP: %s\r\n' % (addr[0]))
								f.write('MAIL FROM: <%s>\r\n' % mail['MAIL_FROM'])
								f.write('MAIL FROM ALT: <%s>\r\n' % mail['MAIL_FROM_ALT'])

								conn.sendall('250 2.1.0 %s... Sender ok\r\n' % (mail['MAIL_FROM']))
								common.printLOG('%s | MAIL FROM: <%s>' % (key19, mail['MAIL_FROM']), 'esmtpd')

								mail['STATE'] = 'RCPT_TO'
					#-----------------------------------------------------------
					# cmdStr.startswith('RCPT TO:') and mail['STATE'] in ('RCPT_TO', 'DATA')
					#-----------------------------------------------------------
					elif cmdStr.startswith('RCPT TO:') and mail['STATE'] in ('RCPT_TO', 'DATA'):
						#-------------------------------------------------------
						# EAI Implementation
						#-------------------------------------------------------
						# Check the length of RCPT TO command(EAI SMTP Extension 2.1.4)
						# The maximum length of MAIL and RCPT command : 460 characters
						lineStrLength = len(lineStr.decode('utf-8'))
						if (lineStrLength > 460):
							conn.sendall('550 5.5.4 %s... Syntax Error (460 characters limit)\r\n' % (lineStr))
							common.printLOG('%s | 550 %s... Syntax Error (460 characters limit)' % (key19, lineStr), 'esmtpd')

						# The number of occurrences of Left Angle Bracket
						lbracket = lineStr[8:].count('<')
						# The number of occurrences of Right Angle Bracket
						rbracket = lineStr[8:].count('>')

						# Need to add functions for the followings:
						# Email Regular Expression Syntax Validation Check for IDN@IDN
						#-------------------------------------------------------
						if ((lbracket == 0) & (rbracket == 0)):
							RCPT_TO = lineStr[8:].strip().strip('<>').lower()
							RCPT_TO_ALT = ''
							print "No angle brackets"
						#-------------------------------------------------------
						elif ((lbracket == 1) & (rbracket == 1)):
							RCPT_TO_STRIP = lineStr[8:].strip().strip('<').upper()

							# The lowest index in the string where "ALT-ADDRESS=" is found
							ALTADDRESS = RCPT_TO_STRIP.decode('utf-8').find("ALT-ADDRESS=")

							#---------------------------------------------------		
							# If there is ALT-ADDRESS
							#---------------------------------------------------		
							if ( ALTADDRESS != -1 ):
								RCPT_TO = str(RCPT_TO_STRIP.partition('>')[0].strip().lower())

								RCPT_TO_ALT = str(RCPT_TO_STRIP.decode('utf-8')[ALTADDRESS:].strip().lower())
								RCPT_TO_ALT = str(RCPT_TO_ALT.decode('utf-8').partition('=')[2].strip().lower())

								print "RCPT TO: " + RCPT_TO
								print "RCPT TO ALT: " + RCPT_TO_ALT

								# EAI SMTP Extension 2.4
								# ALT-ADDRESS value MUST be an all-ASCII email address
								if re.match("^[a-zA-Z0-9._%-]+@[a-zA-Z0-9._%-]+\.[a-zA-Z]{2,6}$", RCPT_TO_ALT) == None:
									print "ALT-ADDRESS Syntax Error"
									conn.sendall('550 5.5.4 %s... Syntax Error\r\n' % (lineStr))
									common.printLOG('%s | 550 %s... Syntax Error' % (key19, lineStr), 'esmtpd')
							else:
								RCPT_TO = str(RCPT_TO_STRIP.partition('>')[0].strip())
								RCPT_TO_ALT = ''
						#-------------------------------------------------------
						else:
							print "Syntax Error"
							conn.sendall('550 5.5.4 %s... Syntax Error\r\n' % (lineStr))
							common.printLOG('%s | 550 %s... Syntax Error' % (key19, lineStr), 'esmtpd')
						#-------------------------------------------------------
						# Convert IDN
						RCPT_TO = common.convertIDN(RCPT_TO)
						#-------------------------------------------------------
						# Check if there is such a user 
						retStr = common.searchUserPath(RCPT_TO)[1]

						if retStr == 'no user':
							conn.sendall('550 5.1.1 %s... User unknown\r\n' % (RCPT_TO))
							common.printLOG('%s | 550 %s... User unknown' % (key19, RCPT_TO), 'esmtpd')
						elif retStr == 'size over':
							conn.sendall('550 %s... Mailbox is full\r\n' % (RCPT_TO))
							common.printLOG('%s | 550 %s... Mailbox is full' % (key19, RCPT_TO), 'esmtpd')
						elif retStr == 'no domain' and mail['ACCESS'] != 'relay' and common.search_access(RCPT_TO, ['to', 'both'])[2] != 'relay':
							conn.sendall('550 %s... Relay denied\r\n' % (RCPT_TO))
							common.printLOG('%s | 550 %s... Relay denied' % (key19, RCPT_TO), 'esmtpd')
						else:
							conn.sendall('250 2.1.5 %s... Recipient ok\r\n' % (RCPT_TO))
							if retStr == 'no domain':
								if not RCPT_TO in mail['RELAY_TO']:
									f.write('RELAY TO: <%s>\r\n' % (RCPT_TO))
									if RCPT_TO_ALT != '':
										f.write('RELAY TO ALT: <%s>\r\n' % (RCPT_TO_ALT))
									print "****************************************"
									print "RELAY: " + RCPT_TO
									print "RELAY ALT: " + RCPT_TO_ALT
									print "****************************************"

									common.printLOG('%s | RELAY TO: <%s>' % (key19, RCPT_TO), 'esmtpd')
									mail['RELAY_TO'].append(RCPT_TO)

									mail['RELAY_TO_ALT'].append(RCPT_TO_ALT)
							else:
								if not RCPT_TO in mail['RCPT_TO']:
									f.write('RCPT TO: <%s>\r\n' % (RCPT_TO))
									common.printLOG('%s | RCPT TO: <%s>' % (key19, RCPT_TO), 'esmtpd')
									mail['RCPT_TO'].append(RCPT_TO)
							mail['STATE'] = 'DATA'
					#-----------------------------------------------------------
					# DATA
					#-----------------------------------------------------------
					elif cmdStr.startswith('DATA') and mail['STATE'] == 'DATA':
						f.write('DATA\r\n')
						f.write('Received: from %s\r\n'
								'\tby %s with %s programmed by %s\r\n'
								'\tfor <%s>; %s\r\n' % (addr[0], conf['SERVER_NAME'], common.PROGRAM_NAME, common.PROGRAM_MAIL, mail['MAIL_FROM'], time.strftime('%a, %d %b %Y %X +0900')))
						conn.sendall('354 Enter mail, end with "." on a line by itself\r\n')
						common.printLOG('%s | DATA' % key19, 'esmtpd')
						mail['STATE'] = 'DOT'
					#-----------------------------------------------------------
					# QUIT
					#-----------------------------------------------------------
					elif cmdStr == 'QUIT':
						conn.sendall('221 2.0.0 %s closing connection\r\n' % (addr[0]))
						common.printLOG('%s | QUIT' % key19, 'esmtpd')
						mail['STATE'] = 'QUIT'
						break
					#-----------------------------------------------------------
					# REST - the current mail transaction will be aborted
					#-----------------------------------------------------------
					elif cmdStr == 'RSET':
						try: 
							f.close()
						except: 
							common.printLOG("esmtpd | Cannot close %s/%s" % (conf['RECV_QUEUE'], key19), 'error')

						if mail['DOT'] == 1:
							try:
								# /NIDAMail_Data/TEMP/key19
								os.rename('%s/%s' % (conf['RECV_QUEUE'], key19), '%s/%s' % (conf['DECODE_QUEUE'], key19))
							except: 
								common.printLOG("esmtpd  | Cannot rename %s/%s to %s/%s" % (conf['RECV_QUEUE'], key19, conf['DECODE_QUEUE'], key19), 'error')
						else:
							try: 
								os.unlink('%s/%s' % (conf['RECV_QUEUE'], key19))
							except: 
								common.printLOG("esmtpd  | Cannot unlink %s/%s" % (conf['RECV_QUEUE'], key19), 'error')

						key19 = common.makeKEY19(0)

						try: 
							f = open('%s/%s' % (conf['RECV_QUEUE'], key19), 'w')
						except:
							common.printLOG("esmtpd  | Cannot open %s/%s" % (conf['RECV_QUEUE'], key19), 'error')
							mail['STATE'] = 'QUIT'
							break
						else:
							mail['MAIL_FROM'] = ''
							del mail['RCPT_TO'][0:]
							del mail['RELAY_TO'][0:]
							######################################3
							del mail['RELAY_TO_ALT'][0:]
							######################################3
							mail['STATE'] = 'MAIL_FROM'
							mail['RECEIVED'] = 1
							mail['DOT'] = 0
						conn.sendall('250 Reset STATE\r\n')
						common.printLOG('%s | RSET' % key19, 'esmtpd')
					#-----------------------------------------------------------
					# NOOP
					#-----------------------------------------------------------
					elif cmdStr == 'NOOP':
						conn.sendall('250 OK\r\n')
						common.printLOG('%s | NOOP' % key19, 'esmtpd')
					#-----------------------------------------------------------
					# UNKNOWN ESMTP COMMAND
					#-----------------------------------------------------------
					else:
						try: conn.sendall('500 5.5.1 Command unrecognized %s\r\n' % (lineStr.strip()) )
						except: common.printLOG("esmtpd | Cannot sendall('500 5.5.1 Command unrecognized')", 'error')
						common.printLOG('%s | Command unrecognized | %s' % (key19, lineStr.strip()), 'esmtpd')
				#---------------------------------------------------------------
				if buffStr.endswith('\n'): 
					buffStr = ''
				else: 
					buffStr = lineStr
				#---------------------------------------------------------------
	try:
		conn.close()
		f.close()
	except: 
		pass

	common.printLOG('%s | Disconnected from %s:%d' % (key19, addr[0], addr[1]), 'esmtpd')

	# If everything goes well, move the message to the DECODING directory
	if mail['DOT'] == 1:
		try: 
			# /NIDAMail_Data/TEMP/key19 -> /NIDAMail_Data/DECODING/
			os.rename('%s/%s' % (conf['RECV_QUEUE'], key19), '%s/%s' % (conf['DECODE_QUEUE'], key19))
		except: 
			common.printLOG("esmtpd  | Cannot rename %s/%s to %s/%s" % (conf['RECV_QUEUE'], key19, conf['DECODE_QUEUE'], key19), 'error')
	else:
		try: 
			os.unlink('%s/%s' % (conf['RECV_QUEUE'], key19))
		except: 
			common.printLOG("esmtpd  | Cannot unlink %s/%s" % (conf['RECV_QUEUE'], key19), 'error')

################################################################################
# End of def receiveESMTP(conn, addr):
################################################################################


################################################################################
# MAIN
################################################################################
# /NIDAMail_DATA/LOG/esmtpd.YYMMDD.log
common.printLOG('esmtpd | ESMTPD is started', 'common')
################################################################################
# Return a list containing the names of the entries in the "/NIDAMail_DATA/TEMP" directory
list = os.listdir(conf['RECV_QUEUE'])

# Remove the files in the "/NIDAMail_DATA/TEMP" directory
for file in list:
	try: 
		os.unlink('%s/%s' % (conf['RECV_QUEUE'], file))
	except: 
		common.printLOG("esmtpd  | Cannot unlink %s/%s" % (conf['RECV_QUEUE'], file), 'error')

try:
	# Create a new socket object on which the server will listen for incoming requests
	# SOCK_STREAM : TCP, SOCK_DGRAM    
	svrsock = socket(AF_INET, SOCK_STREAM)

	# Set the value of the given socket option - setsockopt(level, optname, value)
	# UDP
	svrsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)

	# Bind the socket to address (ESMTPD_PORT = 25)
	svrsock.bind(('', conf['ESMTPD_PORT']))

	# Listen for connections made to the socket. The backlog argument specifies the maximum number of queued connections and should be at least 1
	# Default = 512
	svrsock.listen(conf['ESMTPD_MAX_THREADS']+1)
except:
	common.printLOG('esmtpd | Port: %s - already in use' % conf['ESMTPD_PORT'], 'error')
	common.printLOG('esmtpd | Port: %s - already in use' % conf['ESMTPD_PORT'], 'console')
	os.sys.exit(-1)

common.setUIDGID('esmtpd')

################################################################################
while 1:
	# Accept a connection
	conn, addr = svrsock.accept()

	# Load configurations
	common.loadConf('esmtpd')
	common.loadVH('esmtpd')
	common.loadAccess('esmtpd')

	# Default value of ESMTPD_TYPE = 'threading'
	# ESMTPD_TYPE = 'fork'
	if conf['ESMTPD_TYPE'] == 'fork':
		pid = os.fork()
		if pid == 0: 
			receiveESMTP(conn, addr)
			break
		else: 
			conn.close()
			th = threading.Thread(target=common.waitPID, args=())
			th.start()
		while(threading.activeCount() > conf['ESMTPD_MAX_THREADS']):
			common.printLOG('esmtpd | fork count is larger than %s' % conf['ESMTPD_MAX_THREADS'], 'error')
			time.sleep(1)
	# ESMTPD_TYPE = 'threading'
	else:
		# class Thread(group=None, target=None, name=None, args=(), kwargs={})
		th = threading.Thread(target=receiveESMTP, args=(conn, addr))
		# Start the thread's activity.
		th.start()
		# Return the number of Thread objects currently alive.
		while(threading.activeCount() > conf['ESMTPD_MAX_THREADS']):
			common.printLOG('esmtpd | thread count is larger than %s' % conf['ESMTPD_MAX_THREADS'], 'error')
			time.sleep(1)
################################################################################
# End of File
################################################################################
